[レポート] AWSクラウドを活用したモバイルゲームの自動テストシステムの構築。『ロマンシング サガ リ・ユニバース』の適用事例セッション #CEDEC2023 #classmethod_game
こんにちは、ゲームソリューション部の入井です。
この記事ではCEDEC 2023で発表されたセッション「『ロマンシング サガ リ・ユニバース』に適用したクラウド完結型のモバイルゲーム自動テストシステム完成までの軌跡」について、内容のまとめとその所感を書いていきます。
セッションの概要
『ロマンシング サガ リ・ユニバース』に適用したクラウド完結型のモバイルゲーム自動テストシステム完成までの軌跡 | CEDEC2023
運営型モバイルゲームは致命的な不具合がなくても、そこに「おもしろさ」がなければ長期的な運営は困難を極めます。
しかしながら、運営型モバイルゲームはテスト実行コストが増加し続ける傾向にあり、「おもしろさ」のテストに時間を
かけることが難しくなっています。
テスト自動化はテスト実行コストを下げるための有効な手段の一つとされていますが、そこには様々な課題が存在します。
本講演では、ゲームに特化した自動テストフレームワークである Airtest を AWS Device Farm 上で動作させることで
クラウド完結にした、自動テストシステムをご紹介します。
システムを実現する過程で遭遇した課題とその解決策をご紹介するので、テスト自動化の導入をご検討されている方、
オンプレミスの端末管理に苦労されている方の力になれればと思います。
さらに、『ロマンシング サガ リ・ユニバース』に自動テストシステムを適用した事例もお話しします。
講演者
山﨑 友貴 氏
株式会社アカツキゲームス
研究開発部
QAエンジニア
氏平 誠司 氏
株式会社アカツキゲームス
ゲーム事業部
サーバエンジニア
自動テスト導入の背景
このセッションでは、運営型モバイルゲームの品質向上のために構築したクラウド自動テストシステムについて紹介されました。
テスト対象について
テストシステム導入の対象となったモバイルゲームタイトルは、『ロマンシング サガ リ・ユニバース(以下ロマサガRS)』です。
ロマンシング サガ リ・ユニバース | SQUARE ENIX
運営型モバイルゲームへの自動テスト導入の様々な難しさ
ロマサガRSのような運営型モバイルゲームでテストを行うことの難しさとして、以下の3つの要因が挙げられました。
- テスト実行コストの高さ
- 増え続けるコスト
- ゲーム構成要素の組み合わせの多さ
テスト実行コストの高さについては、ゲームのアップデートの頻度とその量の多さが原因となっています。
運営型モバイルゲームの運用においては、以下の2種類の更新を繰り返すことになり、その度にテストが必要となるため、必然的にコストが高くなってしまいます。
- 運用レベルの更新
- キャラクターやイベント等の追加・更新
- 週に1回程度の実施
- アセットやマスターデータが更新対象
- 新規開発レベルの更新
- 新機能の追加や既存機能の改修等
- 月に1回程度の実施
- クライアントやサーバーのソースコードが更新対象
増え続けるコストについては、テスト対象となる機能の数がゲームの運営期間が長くなるほど多くなっていくのが原因です。
実際の例として、最初は8,000程度だったリグレッションテストのテストケース数が、バージョンを重ねた結果10,000ケースを超えてしまう例が紹介されました。これは、テスト工数としては60人日かける必要がありました。
ゲーム構成要素の組み合わせの多さについては、テスト対象となる様々なゲームシステムの複雑さから、簡単に組合せ爆発が起こることが原因です。
ロマサガRSでは、バトルだけでも編成、アクション、状態、武器、陣形…と多くの要素があり、これら全ての組み合わせに対して手動でテストを行うのは非常に難しいです。
モバイルゲームへの自動テスト導入の課題
自動テストを行うには専用のツールが必要となりますが、ゲーム業界向けの汎用的なテストツールが少なく、それがゲームに自動テストを導入する上での課題の1つとして紹介されました。
例えば、自動テストの導入が一般的になってきたWeb業界では、SeleniumやAutifyなどの汎用的なテスト自動化ツール・プラットフォームが多く存在します。しかし、ゲーム業界ではテストツールが存在しても自社タイトル向けに最適化されている場合が多く、汎用的なツールは少ないです。一部、ゲーム業界向けに特化したツールも存在しますが、モバイルゲームの分野では導入事例があまりありません。
モバイルゲームへの自動テスト導入が浸透しない理由としては、以下の3点が挙げられました。
- コンテンツの変化が激しく、自動テストが持続できない
- 画面情報のみだと、UI要素の取得が難しい
- 多種多様なデバイスの管理にコストがかかる
コンテンツの変化が激しく、自動テストが持続できない点については、テストが困難な原因の1つである更新頻度や更新量の多さが関わっています。
更新によってテスト対象のゲームに頻繁な変更が発生するため、1度作成したテストが壊れやすくなり、最終的にはテスト自体が使われなくなってしまう、ということが発生しやすいのです。
運営型モバイルゲームというコンテンツの性質上頻繁な更新は避けられないため、変化が頻発することは受け入れて、変化が発生した時に最速で自動テストを修正可能なシステムにすることがこの問題に対する解決策になるとのことです。また、変化しづらいテストを自動化することも重要です。
画面情報のみだと、UI要素の取得が難しい点については、モバイルゲームのUI要素は画像認識で特定する必要がある一方で、ゲームのUIはエフェクトやアニメーションが使われた動的なデザインが多く、それが画像認識の精度を下げ、テスト結果の誤りにも繋がってしまうことが理由になります。
この問題を解決するために、今回の事例では画像認識以外でUI要素を取得できる自動テストフレームワークの採用を検討したとのことです。
多種多様なデバイスの管理にコストがかかる点については、テスト用の物理的なデバイスの用意や維持に様々なコストがかかることが問題となっています。例えばテスト実行用のデバイスを1台導入するだけでも、単純な購入コスト以外にセットアップ作業の人的コストや、運用上のデバイス管理コスト、トラブル対応コスト、部品の買い替えコスト等、様々なコストが発生します。
今回は、そうしたコストの発生を防ぐため、管理が不要なクラウド上のデバイスでテストを実行することを検討したとのことです。
自動テスト導入によって達成したいこと
自動テストの導入によってどのような状態を目指すべきかの説明のために、まず品質コストという言葉が説明されました。これは、より良いゲームを作るのに必要なコストで、不具合が生じないよう予防するためにかかる適合コストと、発生した不具合に対処するためにかかる不適合コストで構成されています。
更に、適合コストは不具合を事前に防ぐための予防コストと、不具合を発見しやすくするための評価コストに分かれます。一方で、不適合コストについてもリリース前に発見した不具合の修正にかかる内部失敗コストと、リリース後に発見した不具合の修正にかかる外部失敗コストに分かれます。
不適合コストが増えれば増えるほど全体的なコストは多くなってしまうため、適合コストを増やした上で不適合コストを増やすことができれば、自動テストは成功したと言えます。
ゲームの開発には要求仕様、設計、コーディングといった形でフェーズがありますが、要求仕様段階で混入した不具合を要求仕様中に修正するコストを1とすると、リリース後になってから修正するコストはその200倍に膨らんでしまいます。こういったコストの増大を防ぐため、不具合が混入したフェーズの中で不具合の発見から修正まで完了させることをフェーズ内阻止と言います。
テストの実行にかかるコストを最小化することによって、コーディングフェーズなどの早い段階でテストを実行可能になり、フェーズ内阻止が実現できるようになります。そしてそれは不適合コストを減らすことに繋がります。今回の事例では、自動テストはこの状態を目指すために導入したとのことです。
どのようなテストを行うべきかの話の前に、ユニットテストとE2Eテストがそれぞれ得意とする領域について解説がありました。
全てが自動化に向いているわけではなく、ゲームの面白さやアクセシビリティなどの非機能部分について確認するテストは、手動でのE2Eテストが向いているとのことです。
テストの頻度と回数を増やすには、変化しづらいテストを自動化する必要があります。例えば、E2Eテストの中のリグレッションテストやスモークテストが対象となります。
リグレッションテストはデグレード(プログラムの修正の影響で他の正常だった部分に不具合が出ること)が発生していないかを確認するテストで、同じテストを繰り返すことで効果を発揮します。
スモークテストは、プログラムの修正後にゲームが最低限の動作をするかを確かめるテストで、全てのリリース時に行う基本動作のチェックが自動化の対象になります。
持続可能な自動テストシステムのための技術紹介
ゲームに特化した自動テストフレームワーク
今回の事例で採用した自動テストフレームワークは、NetEase社が開発しているAirtestです。
ゲームのテスト用に開発されたツールで、様々なプラットフォームに対応しています。Pythonによる直感的なテストスクリプトが可能で、独自のIDEも用意されています。
アプリ側に手を加えずにテストを実行可能ですが、Airtestのみでは先ほど自動テストの課題として挙がった画像認識の問題を解決できません。
そこで、AirtestだけでなくPocoというツールも使われています。これは、Airtestと同じくNetEase社が公開しているテストフレームワークで、ゲームのUI関係のテストを行うための機能を持っています。
ゲームからUIオブジェクトの位置や階層構造などの情報を解析し、それに対してスクリプトから操作を行うことが可能です。
AirtestProject/Poco: A cross-engine test automation framework based on UI inspection
クラウド上で様々なデバイスのテストができるAWS Device Farm
テストを実行するためのモバイルデバイス環境としては、AWS Device Farmが採用されました。これは、クラウド上にホストされている物理モバイルデバイスで様々なテストを行うことができるサービスで、テストの実行ログや、スクリーンショット・動画保存機能など、テストに役立つ様々な機能が標準で用意されています。
デバイス管理を利用者側でする必要がなく、必要に応じて簡単に環境を用意できるため、テストの作成に集中することができます。
AWS Device Farm (AWS クラウドで実際のデバイスを使用してアプリをテスト) | AWS
AWS Device Farm の記事一覧 | DevelopersIO
Device Farmの環境は、テストを実行するデバイスと、それを操作するホストマシンで構成されています。
Device Farmでのデバイスの利用形態としては、デバイスを専有するプライベートデバイスと、デバイスは専有せずテストごとに環境がクリーンアップされるパブリックデバイスの2種類があり、今回はパブリックデバイスが採用されました。これは、プライベートデバイスは構築して利用できるようになるまで時間がかかり、スケールしづらいという理由からです。
テストを実行するためには、以下の3つのファイルが必要となります。
- テストスクリプトなどをまとめたzip
- 実行の手順を記述したYAML
- テスト対象のアプリケーション
DeviceFarm上では、これらのファイルを活用して以下のようなフローでテストを実行したとのことです。
クラウド完結型の自動テストシステム完成までの軌跡
Pythonによるテスト実行環境の整備
今回のテストシステムの要件の1つとして、どの環境においても同一のテストスクリプトで同様のテスト結果になることが挙げられました。これは、テスト対象のゲームの激しい変化に対応して最速でテストスクリプトを修正可能にするために必要となります。
自動テストの環境としては、本番テスト実行用の環境とスクリプト開発用の環境の2つがあります。
本番テスト実行用の環境では、エンジニア以外でも自動テストが実行できるように、Jenkins等によるGUIの実行トリガーが必要となりました。それ以外にも、テストを手軽に実行するためにローカルマシンからDeviceFarmを実行できるトリガーも必要となりました。
スクリプト開発用の環境では、効率的にテストスクリプトのデバッグが行えるように、実行環境としてローカルマシンが使用されます。実行方法としてCLIやIDEが利用でき、特にIDEはUI操作コードの自動生成に使用されます。
なお、実行環境としてはDeviceFarmのホストマシンはUbuntu 14.04、ローカルマシンはmacOS 13を前提にしています。
これらの環境全てで、同一のテストスクリプトが同一の結果を返すように動作することを目指していきます。
最初に、テストスクリプトを実行するPythonのバージョンを全環境で統一したとのことです。
統一先のバージョンとしては、Airtestが保証している上限である3.9が選択されました。ローカルマシンについてはpipenvの活用でバージョンの固定ができましたが、DeviceFarmのホストマシンでは実行ユーザーの権限が弱く任意のバージョンのPythonインストールが行えません。そこで、ローカルでビルドしたPythonをDeviceFarmにアップロードすることで、全環境でのバージョン統一を実現しました。
Airtestのテストスクリプトをテストケースごとに作成していく際、Airtestの初期設定やテスト対象アプリケーションの実行など、各スクリプトで同じ内容の記述をしている箇所が非常に多く存在しました。そこで、共通処理をまとめて書いておくランチャースクリプトを作成することで、スクリプトの記述量を減らすことにしました。
ランチャースクリプトは、pytestの記法で作成したものを使用しています。Airtestは、内部でunittestというテストフレームワークを使用していますが、fixture機能を利用するためにunittestと互換性あるpytestを使用することにしたとのことです。
pytest: helps you write better programs — pytest documentation
テスト実行の際に必要なパラメータとして、DeviceFarmの実行デバイスやタイムアウト指定、テストスクリプトのテストシナリオや接続サーバの指定など、数がかなり多くなっていたため、Invokeというタスクランナーを導入しました。Invokeを活用することで、DeviceFarmでのテストの実行等の一連の作業をタスクとしてまとめることが可能になりました。
Welcome to Invoke! — Invoke documentation
DeviceFarm環境の調整
DeviceFarm上でテストを実行しようとした時、最初の課題になったのはAirtestがDeviceFarmで公式サポートされていないという点でした。これは、AirtestをDeviceFarmでサポートされているAppiumだと認識させることで解決できました。
AirtestをAppiumと認識させるにあたっては、ディレクトリやファイル構成をAppiumと合わせたり、テスト実行時にAirtestのadbとDeviceFarm上のadbが衝突するのを防ぐため、Airtest側のadbをDeviceFarmのものに差し替える等の対応が必要となりました。
DeviceFarmでのテストの際、任意のバージョンのアプリケーションをテスト対象にできるようにする必要がありますが、これは既存のビルドフローにDeviceFarmへのアップロードフローを追加することで実現しました。DeviceFarmへのアップロード時に取得できるARNをAmazon S3に保管しておくことで、DeviceFarm起動時にオプションで任意のアプリバージョンを指定できるようにしています。
テスト対象である開発環境ゲームサーバはAWS VPC上で稼働しており、セキュリティのためにVPCにIP制限をかけています。VPCエンドポイントを使用すればIP制限を通り抜けることが可能ですが、DeviceFarmのパブリックデバイスはVPCエンドポイントにアクセスする機能を持っていません。これについては、パブリックデバイスでClient VPNを活用することでアクセスを可能にしました。
テスト結果を見るためのレポートや通知の設計
テストの実行結果についてはAmazon S3に保管することで一元管理し、Webホスティング機能を活用して閲覧できるようにしています。これは、自動テストの結果を様々な視点から確認できるようにすることで、テスト失敗時のトラブルシュート速度を上げることを目的にしています。
保管形式の1つとして、Airtest標準レポートがあります。これは、テストの結果やテスト実行時に保管したスクリーンショットなどを1つの画面で閲覧することが可能なレポートです。
DeviceFarmのテスト実行動画の録画機能も使用しています。
テスト実行者がその結果の通知をSlackで受け取れるようにパイプラインも構築しました。
流れとしては、DeviceFarmでのテスト実行後、そのテストの終了をポーリングで検知し、その後DeviceFarmから取得した各種アーティファクトをAmazon S3へアップロードします。そして、アーティファクトの内容をまとめて閲覧できるURLをSlackへ通知します。これにより、テスト実行者はテスト結果の通知を受け取ることができます。
『ロマンシング サガ リ・ユニバース』への適用事例
ロマサガRSに今回の自動テストシステムを導入するにあたり、システムを安定化させるためにまずはチュートリアルを突破するスモークテストにシステムを試験的に適用しました。これは、既に膨大な数が存在する手動のリグレッションテストケースを自動テストに変換するコストが、スモークテストよりも高かったためです。
ロマサガRSのテストスクリプトを実装したことで、自動化が難しいテスト対象や、自動化の難易度を引き上げている要因などが分かりました。
自動化が難しいテスト対象
まず、自動化が難しかったテスト対象としては、以下の3点が挙げられました。
- 慣性が働くスクロールリストビュー
- 同じクラス名のUIオブジェクト
- 動的に位置が変化するUIオブジェクト
慣性が働くスクロールリストビューについては、スワイプの力加減の調整が難しくスクロールし過ぎてしまったり、対象のUIオブジェクトが画面上に表示されていることを検知できない点が理由として挙げられました。
これらの課題は、適切な強さでスワイプする汎用関数や、UIオブジェクトがタップ可能であることを検知する関数の実装により、解決したとのことです。
同じクラス名のUIオブジェクトについては、同じUIデザインを画面内に複数配置しているケースなどで、UIオブジェクト検索時、クラス名がユニークでないUIオブジェクトはオブジェクトのヒエラルキーの順番に選択されるPocoの仕様から、テスト対象オブジェクトが一意に定まらないことが課題として挙げられています。
こちらの課題については、UIオブジェクトのtextの内容等のユニークな情報で判定する形で解決しました。
動的に位置が変化するUIオブジェクトについては、こういったUIオブジェクトを特定する汎用的な手段がないことが理由として挙げられました。
これも、オブジェクト内部のユニークな情報から特定することで解決可能ですが、UIオブジェクトの位置がどのようなルールで変更されるのかなどの仕様をあらかじめプランナーにヒアリングしておくことで、無駄のない自動テストを書くことが可能とのことです。
テスト自動化に求められるスキル
自動化の難易度を引き上げている理由として、以下のスキルが求められることが挙げられました。
- ゲーム開発スキル
- コミュニケーションスキル
ゲーム開発スキルについては、自動テストを効率良く実行するためにはSDKやデバッグ機能などをテスト対象のゲームに実装する活動が必要であり、そのためにはゲームのアーキテクチャ等を理解した上で開発エンジニアと合意を得なければならず、ゲームの開発経験が自然と求められることが理由として挙げられています。
コミュニケーションスキルについては、自動テストシステムの導入にあたり、AWSやjenkinsの権限を付与してもらうには信頼関係の構築が必要だったり、プロダクトのリリースサイクルを理解するために情報を各関係者から積極的に取りに行かなければならないことが理由として挙げられました。
今回、テスト自動化システムを試験的に導入した結果としては、システムの完成度を高めることはできましたが、実運用には至らない形となりました。その理由として、アプリ側に必要となるデバッグ機能の実装に苦戦したことなどがあります。
自動化の実運用のためには、スモークテストだけでなく、大量のリグレッションテストもassertによる結果比較ができるようにしていく必要があります。
テストを自動化するコストは決して低くないため、費用対効果が高いテストを自動化対象に選定することが、テストを実運用にする上で重要になると感じたとのことでした。
今後の展望
価値のある自動テストを効率良く増やしていけるかが課題であり、そのためには費用対効果の高い自動テストの選定と実装をしつつ、assertによる結果比較を行う自動テストの実装を進める必要があるとのことです。
また、DeviceFarmではiOSのテストも対応しているため、今後はAndroidだけでなくiOSもテスト対象にしていく他、Productionバイナリにおける自動テストの実施方法も検討していきたいとのことです。
感想
ゲームへの自動テスト導入のための方法について、かなり具体的な部分まで解説があり非常に勉強になったセッションでした。
自動テストは上手く活用すれば品質維持の上で高い効果を発揮しますが、導入のためには多くのコストやスキルが求められるため、セッションの中でも解説されているように適切なテスト対象を選定するためのテスト設計が非常に重要と感じました。